#pragma once

#include "IConnection.h"

class Connection : public IConnection
{
public:
	Connection();
	virtual ~Connection();

public:
	BEGIN_DEFINE_CLASS(CLSID_Connection)
		DEFINE_INTERFACE_ENTRY(IConnection)
	END_DEFINE_CLASS()

	//struct parent_child_relation{
	//private:parent_child_relation(){}
	//public: 
	//	void AddChild(objectid child,parent_child_relation& childrelation){
	//		childrelation.parent = parent;
	//		childobjects.push_back(child);
	//	}
	//	void RemoveChild(objectid child,parent_child_relation& childrelation){
	//		objectidarray::iterator itfind = std::find(childobjects.begin(),childobjects.end(),child);
	//		if(itfind != childobjects.end()){
	//			childobjects.erase(itfind);
	//			childrelation.parent = OBJID_NULL;
	//		}
	//	}
	//	void DisposeChild(objectid child,parent_child_relation& childrelation){
	//		objectidarray::iterator itfind = std::find(childobjects.begin(),childobjects.end(),child);
	//		if(itfind != childobjects.end()){
	//			childobjects.erase(itfind);
	//			childrelation.parent = OBJID_NULL;
	//		}
	//	}
	//	objectid parent;
	//	objectidarray childobjects;
	//};
	//struct weak_reference_relation{
	//	objectidarray weakrefobjects;
	//};
	//struct share_reference_relation{
	//	objectidarray sharerefobjects;
	//};
	struct ObjectNode
	{
	public:
		enum{
			kBitMask_31b	=0x80000000,
			kBitMask_30b	=0x40000000,
			kBitMask_0_30b	=0x7FFFFFFF,
			kBitMask_0_29b	=0x3FFFFFFF,
		};
		uint32		m_dwFlag;	// bit 31:		Alloced
								// bit 0-30:	alloced: 0
								//				free: next free node idx, last: objectID's count
		long		m_dwPreNodeIDx;// bit 31:		no used
								   // bit 0-30:	alloced: 0  
								   // free: prev free node idx
								   // first: -1
		IObject*	m_pObject;

		objectid m_parent;
		objectidarray m_childobjects;

		objectidarray m_weakrefobjects;

		objectidarray m_sharerefobjects;
		objectidarray m_refobjects;

		void Init()
		{
			m_dwFlag=0;
			m_dwPreNodeIDx=0;
			ASSERT(m_pObject==NULL);
			m_pObject=NULL;
			m_parent = OBJID_NULL;
		}
		void FreeObject()
		{
			ASSERT(IsAlloced());
			ASSERT(m_pObject);
			m_pObject->ReleaseObject();
			m_pObject=NULL;
		}
		void Alloc()
		{
			ASSERT(!IsAlloced());
			m_dwFlag|=kBitMask_31b;
		}
		bool IsAlloced() const
		{
			return (m_dwFlag&kBitMask_31b)!=0;
		}
	private:
		friend class Connection;
	};

	struct ObjectPage
	{
	private:
		enum{
			kObjectPageSize=0x00000200,	//object count in one page
		};
		ObjectNode	m_aNodes[kObjectPageSize];
	private:
		friend class Connection;
	};

public:
	event_implement(ObjectCreatedEventHandler,ObjectCreated)
	event_implement(ObjectModifyingEventHandler,ObjectModifying)
	event_implement(ObjectModifiedEventHandler,ObjectModified)
	event_implement(ObjectDeletingEventHandler,ObjectDeleting)
	event_implement(ObjectDeletedEventHandler,ObjectDeleted)

	virtual IObject* FindParent(objectid child);
	virtual vresult CreateChild(objectid parent,vclsid childclsid,objectid* pobjectid);
	virtual vresult CreateChild(objectid parent,vclsid childclsid,IObject** ppchild);
	virtual vresult CreateWeakReference(objectid one,objectid another);
	virtual vresult CreateShareReference(objectid one,objectid shared);
	virtual uint32 GetChildrenCount(objectid object) const;
	virtual uint32 GetWeakWeakReferencesCount(objectid object) const;
	virtual uint32 GetShareReferencesCount(objectid object) const;
	virtual uint32 FindChildren(objectid object,objectidarray& children) const;
	virtual IObject* FindChild(objectid object,const String& name) const;
	virtual uint32 FindWeakWeakReferences(objectid object,objectidarray& weakrefs) const;
	virtual uint32 FindShareReferences(objectid object,objectidarray& sharerefs) const;

	virtual vresult CreateObject(vclsid clsID,IObject** ppobject);

	virtual vresult CreateObject(vclsid clsID,objectid* pObjID);
	virtual vresult CreateObjectAt(vclsid clsID,objectid objID);
	virtual vresult CreateDummyObject(objectid* pObjID);
	virtual vresult QueryVInterface(objectid oid,viid iid,IInterface** ppInterface);
	virtual vresult ReleaseObject(objectid oid);
	virtual void ReleaseObject(const objectidarray& arrObjID);
	virtual vresult ReleaseReservedNode();
	virtual vclsid GetClassID(objectid oid);
	virtual bool IsValidObjectId(objectid oid)const;
	inline virtual void PutIntoRecycleBin(objectid oid);
	inline virtual void ClearRecycleBin();
	virtual vresult CreateObjectAt(vclsid clsID,objectid objID,IObject** pObject);
	virtual vresult DirectReleaseObject(objectid oid);

	virtual IObject* FindObject(objectid oid) const;
	virtual ITransaction* GetTransaction()  const;

private:
	uint32 PrepareEmptyObjectInfo(/*ObjectNode* pObjectNode = NULL*/);
	void PrepareEmptyObjectInfo(objectid oid);
	bool AppendOnePage();
	ObjectNode* GetNodeFromID(objectid oid)const;
	vresult ReleaseAndReserveObject(objectid oid);

private:
	void PutIntoTail(ObjectNode* pObjectNode,objectid oid);
	void PutIntoReserveTail(ObjectNode* pObjectNode,objectid oid);
	void PutReserveObjectsIntoTail();
	void PutIntoHead(ObjectNode* pObjectNode,objectid oid);
	void PutIntoReserveHead(ObjectNode* pObjectNode,objectid oid);
	void PutReserveObjectsIntoHead();
	void OnPropertyChanging(int32 propertyid,objectid objid,IObject* object);

private:
	enum{
		kObjectPageMaxCount=0x400000,
		kObjectNode_Error=0xFFFFFFFF,
	};
	std::vector<ObjectPage*>	m_aPPages;
	uint16			m_nPageCount;
	uint32			m_nTotalObject;		// objectID's count
	uint32			m_nHeadPtr;

	//TEST
	uint32			m_nTailPtr;
	uint32			m_nHeadReservedPtr;
	uint32			m_nTailReservedPtr;
	bool			m_bPutIntoTail;		// put released objects to tail
	objectidarray	m_RecycleBin;
	mutable sys::ObjectPtr		m_objTransaction;
};

AUTO_REGISTER_CLASSMAP_ENTRY(Connection)